# -*- coding: utf-8 -*-
'''
Created on 17-05-2011

@author: Filon
'''

import re

'''
Function responsible for validating format and limits
'''

def is_valid(format, min, max):
    if format == "%H:%M":
        H1 = min[0:2]
        M1 = min[3:5]
        
        H2 = max[0:2]
        M2 = max[3:5]
        
        if len(min) != 5:
            raise Exception('min has wrong format')
        if len(max) != 5:
            raise Exception('max has wrong format') 
        
        
        if H1 > '23' or H1 < '00' or M1 > '59' or M1 < '00':
            raise Exception('min has wrong format') 
       
        if H2 > '23' or H2 < '00' or M2 > '59' or M2 < '00':
            raise Exception('max has wrong format') 
       
       
        
        if H1 > H2:
            raise Exception('min is higher than max')
        elif H1 == H2 and M1 > M2:
            raise Exception('min is higher than max')
        else:
            if (int(H2) - int(H1)) > 1:
                return 2
            elif (int(H2) - int(H1)) == 1:
                return 1
            else:
                return 0
    else:
        raise Exception('unsuported format. Try: %H:%M')

'''
Function responsible for creating regexp for instance when both hours are the same
'''

def reg_time0(min, max):   
    
    H11 = min[0:1]
    M11 = min[3:4] 
    H12 = min[1:2]
    M12 = min[4:5]
    
    H21 = max[0:1]
    M21 = max[3:4] 
    H22 = max[1:2]
    M22 = max[4:5]
    
    if M11 == M21:
        return H11 + H12 + ':' + M11 + '[' + M12 + '-' + M22 + ']'
    if int(M21) - int(M11) == 1:
        return '(' + H11 + H12 + ':' + M11 + '[' + M12 + '-9])|(' + H11 + H12 + ':' + M21 + '[0-' + M22 + '])'
    if int(M21) - int(M11) > 1:
        return '(' + H11 + H12 + ':' + M11 + '[' + M12 + '-9])|(' + H11 + H12 + ':' + M21 + '[0-' + M22 + '])|(' + H11 + H12 + ':' + '[' + str(int(M11) + 1) + '-' + str(int(M21) - 1) + ']' + '[0-9])'


'''
Function responsible for creating regexp for instance when there is one hour difference between hours
'''
def reg_time1(min, max):      
    H11 = min[0:1]
    M11 = min[3:4] 
    H12 = min[1:2]
    M12 = min[4:5]
    
    H21 = max[0:1]
    M21 = max[3:4] 
    H22 = max[1:2]
    M22 = max[4:5]
    
    if M11 == M21:
        return r'(' + H11 + H12 + ':[' + M11 + '-5]' + '[' + M12 + '-9])|' + '(' + H21 + H22 + ':[0-' + M21 + ']' + '[0-' + M22 + '])'
    elif int(M11) < 5 and int(M21) > 0:
        return r'(' + H11 + H12 + ':[' + str(int(M11) + 1) + '-5]' + '[0-9])|' + '(' + H11 + H12 + ':' + M11 + '[' + M12 + '-9])|' + '(' + H21 + H22 + ':[0-' + str(int(M21) - 1) + ']' + '[0-9])|' + '(' + H21 + H22 + ':' + M21 + '[0-' + M22 + '])'
    elif int(M11) < 5 and int(M21) == 0:
        return r'(' + H11 + H12 + ':[' + str(int(M11) + 1) + '-5]' + '[0-9])|' + '(' + H11 + H12 + ':' + M11 + '[' + M12 + '-9])|' + '(' + H21 + H22 + ':' + M21 + '[0-' + M22 + '])'
    elif int(M11) == 5 and int(M21) > 0:
        return r'(' + H11 + H12 + ':' + M11 + '[' + M12 + '-9])|' + '(' + H21 + H22 + ':[0-' + str(int(M21) - 1) + ']' + '[0-9])|' + '(' + H21 + H22 + ':' + M21 + '[0-' + M22 + '])'
    else:
        return r'(' + H11 + H12 + ':' + M11 + '[' + M12 + '-9])|' + '(' + H21 + H22 + ':' + M21 + '[0-' + M22 + '])'


'''
Function responsible for creating regexp for instance when there is more than one hour difference between hours
'''
def reg_time2(min, max):  
    H1 = min[0:2]
    M1 = min[3:5]
        
    H2 = max[0:2]
    M2 = max[3:5] 
     
    H11 = min[0:1]
    M11 = min[3:4] 
    H12 = min[1:2]
    M12 = min[4:5]
    
    H21 = max[0:1]
    M21 = max[3:4] 
    H22 = max[1:2]
    M22 = max[4:5]
    
    ret = ''
     
    
    if M11 == M21:
        ret = '(' + H11 + H12 + ':[' + M11 + '-5]' + '[' + M12 + '-9])|' + '(' + H21 + H22 + ':[0-' + M21 + ']' + '[0-' + M22 + '])'
    elif int(M11) < 5 and int(M21) > 0:
        ret = '(' + H11 + H12 + ':[' + str(int(M11) + 1) + '-5]' + '[0-9])|' + '(' + H11 + H12 + ':' + M11 + '[' + M12 + '-9])|' + '(' + H21 + H22 + ':[0-' + str(int(M21) - 1) + ']' + '[0-9])|' + '(' + H21 + H22 + ':' + M21 + '[0-' + M22 + '])' 
    elif int(M11) < 5 and int(M21) == 0:
        ret = '(' + H11 + H12 + ':[' + str(int(M11) + 1) + '-5]' + '[0-9])|' + '(' + H11 + H12 + ':' + M11 + '[' + M12 + '-9])|' + '(' + H21 + H22 + ':' + M21 + '[0-' + M22 + '])' 
    elif int(M11) == 5 and int(M21) > 0:
        ret = '(' + H11 + H12 + ':' + M11 + '[' + M12 + '-9])|' + '(' + H21 + H22 + ':[0-' + str(int(M21) - 1) + ']' + '[0-9])|' + '(' + H21 + H22 + ':' + M21 + '[0-' + M22 + '])' 
    else:
        ret = '(' + H11 + H12 + ':' + M11 + '[' + M12 + '-9])|' + '(' + H21 + H22 + ':' + M21 + '[0-' + M22 + '])'


    if(H11 == H21):
        two = '|(' + H11 + '[' + str(int(H12) + 1) + '-' + str(int(H22) - 1) + ']:[0-5][0-9])'
    elif int(H1) < 9 and int(H2) > 20:
        two = '|(0[' + str(int(H12) + 1) + '-9]:[0-5][0-9])' + '|(1[0-9]:[0-5][0-9])' + '|(2[0-' + str(int(H22) - 1) + ']:[0-5][0-9])'
    elif int(H1) < 9 and int(H2) > 10:    
        two = '|(0[' + str(int(H12) + 1) + '-9]:[0-5][0-9])' + '|(1[0-' + str(int(H22) - 1) + ']:[0-5][0-9])'
    elif int(H1) > 9 and int(H2) > 20:
        two = '|(1[' + str(int(H12) + 1) + '-9]:[0-5][0-9])' + '|(2[0-' + str(int(H22) - 1) + ']:[0-5][0-9])'
   
        
    return r'' + ret + two;

'''
Function responsible for validating format and limits
'''
def is_valid_date(format, min, max):
    if format == "%Y-%m-%d":
        Y1 = min[0:4]
        M1 = min[5:7]
        D1 = min[8:10]
        
        Y2 = max[0:4]
        M2 = max[5:7]
        D2 = max[8:10]

        
        if int(Y1) < 1970 or int(Y1) > 2099 or int(Y2) < 1970 or int(Y2) > 2099:
            raise Exception('Bad year')
        if int(M1) < 0 or int(M1) > 12 or int(M2) < 0 or int(M2) > 12:
            raise Exception('Bad month')
        if  int(D1) < 0 or int(D1) > 31 or int(D2) < 0 or int(D2) > 31:
            raise Exception('Bad day')
        else:
            if int(Y1) == int(Y2) and int(M1) == int(M2):
                return 0
            elif int(Y1) == int(Y2) and int(M2) - int(M1) == 1:
                return 1
            elif int(Y1) == int(Y2):
                return 2
            elif int(Y2) - int(Y1) == 1:
                return 3
            else:
                return 4
    else:
        raise Exception('unsuported format. Try: %Y-%m-%d')

'''
Function responsible for creating regexp for all years
'''    
def year(min, max):    
    
    return r'((((19|20)(([02468][048])|([13579][26]))-02-29))|((20[0-9][0-9])|(19[0-9][0-9]))-((((0[1-9])|(1[0-2]))-((0[1-9])|(1\d)|(2[0-8])))|((((0[13578])|(1[02]))-31)|(((0[1,3-9])|(1[0-2]))-(29|30)))))'       

'''
Creates regexp
'''   
def run(format, min = None, max = None):
    if min == None:
        dmin = "1970-01-01"
        tmin = "00:00"
    if max == None:
        dmax = "2099-12-31"
        tmax = "23:59"
        
    date = ''
    time = ''
    
    
    if is_valid_date("%Y-%m-%d", dmin, dmax) >= 0:
        date = year(dmin, dmax)
    if is_valid('%H:%M', tmin, tmax) == 0:
        time = reg_time0(tmin, tmax)
    elif is_valid('%H:%M', tmin, tmax) == 1:
        time = reg_time1(tmin, tmax)
    else:
        time = reg_time2(tmin, tmax)
    time = r'(' + time + ')(\+((0[0-9])|(1[1-2])))?'

    return r'^' + date + '\s' + time + '$'

if __name__ == '__main__':
    xxx3 = run("%Y-%m-%d %H:%M")
    print (xxx3)
    
    print(re.match(xxx3, "2000-03-29 23:34"))
